package com.woniu.adapter;


import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.woniu.outlet.dao.MessagePoMapper;
import com.woniu.outlet.dao.WorkerPoMapper;
import com.woniu.outlet.po.MessagePo;
import com.woniu.outlet.po.WorkerPo;
import com.woniu.outlet.rabbitmq.MessageRepo;
import com.woniu.outlet.redis.RedisWorkerRepo;
import com.woniu.utils.MessageStatus;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class WorkerAdapter {

    @Autowired
    private WorkerPoMapper workerPoMapper;

    @Autowired
    private MessagePoMapper messagePoMapper;

    @Autowired
    private RedisWorkerRepo redisWorkerRepo;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private MessageRepo messageRepo;

    @Autowired
    private PasswordEncoder PasswordEncoder;

    public List<WorkerPo> findWorkers() throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        String str = redisWorkerRepo.findWorkers("worker:list");
        List<WorkerPo> lists = new ArrayList<>();
        if (!StringUtils.isEmpty(str)) {
            lists = mapper.readValue(str, new TypeReference<List<WorkerPo>>() {
            });
            return lists;
        }
        lists = workerPoMapper.selectByExample(null);
        //存到redis
        redisWorkerRepo.saveWorker("worker:list", mapper.writeValueAsString(lists));
        return lists;
    }

    public WorkerPo getWorkerById(Long id) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        String str = redisWorkerRepo.findWorkers("worker:" + id);


        WorkerPo workerPo = null;
        if (!StringUtils.isEmpty(str)) {
            workerPo = mapper.readValue(str, new TypeReference<WorkerPo>() {
            });
            return workerPo;
        }
        workerPo = workerPoMapper.selectByPrimaryKey(id);
        //存到redis
        redisWorkerRepo.saveWorker("worker:" + id, mapper.writeValueAsString(workerPo));
        return workerPo;
    }


    public boolean addWorker(WorkerPo workerPo) {
        String username = workerPo.getUsername();

        ValueOperations<String, String> ops = redisTemplate.opsForValue();

        while(!Boolean.TRUE.equals(ops.setIfAbsent("register:"+username,"s",3000, TimeUnit.MILLISECONDS))){
            return false;
        }


        RLock rLock = redissonClient.getLock("register");
        try {
            rLock.lock();
            Thread.sleep(5000);
            WorkerPo workerPo1 = workerPoMapper.selectByUserName(workerPo.getUsername());
            if (workerPo1 != null) {
                return false;
            }


            //添加用户
            workerPo.setPassword(PasswordEncoder.encode(workerPo.getPassword()));
            workerPoMapper.insert(workerPo);
            redisWorkerRepo.deleteWorker("worker:list");
            log.info("发送邮箱消息到rabbitmq=======================");
            //保存要发送的消息内容
            MessagePo message = new MessagePo();
            //未发送
            message.setStatus(MessageStatus.UNSEND.getStatus());
            //消息内容为用户的邮箱信息
            message.setMessageContent(workerPo.getEmail());
            message.setExchange("workMessage_exchange");
            message.setRoutingKey("workMessage.add");
            //重试次数默认是10次
            message.setRetryCount(10);
            message.setVersion(1L);
            messagePoMapper.insertSelective(message);

        } catch (Exception ex) {
            return false;
        } finally {
            rLock.unlock();
        }
        return true;
    }

    public void updateWorker(WorkerPo workerPo) {
        workerPoMapper.updateByPrimaryKeySelective(workerPo);
        redisWorkerRepo.deleteWorker("worker:list");
    }

    public void deleteWorkerById(Long id) {
        workerPoMapper.deleteByPrimaryKey(id);
        redisWorkerRepo.deleteWorker("worker:list");
    }

    public Long getWorkerByCode(String code) {
        WorkerPo workerPo = workerPoMapper.selectByUserName(code);
        return workerPo.getId();
    }

    public String getWorkerByAccount(String account) {
        String password = workerPoMapper.selectByAccount(account);
        return password;
    }
}
